package com.useeinfo.oa.modules.inspection.biz;

import com.useeinfo.framework.extend.biz.CrudBiz;
import com.useeinfo.framework.sugar.data.QueryParam;
import com.useeinfo.framework.sugar.func.file.FileUtils;
import com.useeinfo.framework.sugar.tools.Configuration;
import com.useeinfo.framework.sugar.tools.DateTimeUtils;
import com.useeinfo.framework.sugar.tools.StringConverters;
import com.useeinfo.oa.common.config.ConstantKeyFilePath;
import com.useeinfo.oa.common.utils.ResultUtil.ResultDto;
import com.useeinfo.oa.common.utils.ResultUtil.ResultUtil;
import com.useeinfo.oa.modules.base.biz.AuditFlowBiz;
import com.useeinfo.oa.modules.base.biz.FacilityBiz;
import com.useeinfo.oa.modules.base.biz.PositionBiz;
import com.useeinfo.oa.modules.base.biz.ResourceBiz;
import com.useeinfo.oa.modules.base.entity.*;
import com.useeinfo.oa.modules.base.enums.ResourceTypeEnum;
import com.useeinfo.oa.modules.inspection.dao.PlannerInspectionDao;
import com.useeinfo.oa.modules.inspection.entity.FacilityInspection;
import com.useeinfo.oa.modules.inspection.entity.InspectionOrder;
import com.useeinfo.oa.modules.inspection.entity.PlannerInspection;
import com.useeinfo.oa.modules.inspection.enums.InsOrderAssignTypeEnum;
import com.useeinfo.oa.modules.inspection.enums.InsOrderOperationEnum;
import com.useeinfo.oa.modules.inspection.enums.InsPlannerStatusEnum;
import com.useeinfo.oa.modules.maintaining.biz.PeriodInstallBiz;
import com.useeinfo.oa.modules.maintaining.entity.PeriodInstall;
import com.useeinfo.oa.modules.maintaining.entity.PlannerOrder;
import com.useeinfo.oa.modules.security.biz.OrganizationBiz;
import com.useeinfo.oa.modules.security.biz.SystemUserBiz;
import com.useeinfo.oa.modules.security.entity.SystemUser;
import com.useeinfo.oa.modules.security.util.SessionKeyUtils;
import com.useeinfo.oa.modules.threadUtil.ThreadUtils;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

@Service
public class PlannerInspectionBiz extends CrudBiz<PlannerInspectionDao, PlannerInspection> {
    @Autowired
    private ResourceBiz resourceBiz;
    @Autowired
    private AuditFlowBiz auditFlowBiz;

    @Autowired
    private SystemUserBiz systemUserBiz;
    @Autowired
    private OrganizationBiz organizationBiz;
    @Autowired
    private PeriodInstallBiz periodInstallBiz;
    @Autowired
    private FacilityInspectionBiz facilityInspectionBiz;
    @Autowired
    private PositionBiz positionBiz;
    @Autowired
    private PlannerInspectionLogBiz plannerInspectionLogBiz;
    @Autowired
    private FacilityBiz facilityBiz;
    @Autowired
    private InspectionOrderBiz inspectionOrderBiz;
    @Autowired
    private InspectionExecuteTimeBiz inspectionExecuteTimeBiz;



    /**
     * 开始计划，停止计划
     *
     * @param ids
     * @param request
     * @param type
     * @return
     */
    public ResultDto planner(String ids, HttpServletRequest request, int type, InsPlannerStatusEnum insPlannerStatusEnum) {
        Enterprise enterprise = SessionKeyUtils.getSessionEnterprise(request);
        SystemUser systemUser = SessionKeyUtils.getSessionUser(request);
        if (enterprise == null || systemUser == null) {
            return ResultUtil.error("session过期，请重新登陆");
        }
        net.sf.json.JSONArray jsonArray = net.sf.json.JSONArray.fromObject(ids);
        for (Object id : jsonArray) {
            PlannerInspection plannerInspection = dao.findModel(StringConverters.null2Long(id));
            if (type == 0 && plannerInspection.getInsPlannerStatusEnum().getCode().equals("START")) {
                return ResultUtil.error("不能开始已经开始的计划");
            }
            if (type == 1 && plannerInspection.getInsPlannerStatusEnum().getCode().equals("STOP")) {
                return ResultUtil.error("不能停止已经停止的计划");
            }
        }
        for (Object id : jsonArray) {
            PlannerInspection plannerInspection = dao.findModel(StringConverters.null2Long(id));
            plannerInspection.setInsPlannerStatusEnum(insPlannerStatusEnum);
            dao.update(plannerInspection);
            if(type==1){
                inspectionExecuteTimeBiz.setOperateStatus(0,StringConverters.null2Long(id));
            }else if(type==0){
                inspectionExecuteTimeBiz.setOperateStatus(1,StringConverters.null2Long(id));
            }
            //操作日志
            plannerInspectionLogBiz.savePlannerLog(plannerInspection, type == 0 ? InsOrderOperationEnum.START : InsOrderOperationEnum.END, request);
        }
        return ResultUtil.success();

    }

    /**
     * 保存计划工单
     *
     * @param plannerInspection 巡检-工单计划表
     * @param pic1
     * @param sImg1
     * @param start 计划开始时间
     * @param end 计划结束时间
     * @param selectCompleteAuditFlowIds 完成审批流
     * @param selectDelayAuditFlowIds 延期审批流
     * @param selectOrganizationIds 组织
     * @param selectPeriodInstallIds 所属周期
     * @param request 请求
     * @param facilityMaintainIds
     * @return
     */
    public ResultDto save(PlannerInspection plannerInspection, MultipartFile pic1, String sImg1, String start, String end, List<String> selectCompleteAuditFlowIds,
                          List<String> selectDelayAuditFlowIds, List<String> selectCancelAuditFlowIds, List<String> selectOrganizationIds, List<String> selectPeriodInstallIds,
                          HttpServletRequest request, String facilityMaintainIds,String resourceId) {

        /**
         *  修改计划单，如果没有修改周期，则不生成新工单
          */
        PlannerInspection oldInfo = null;
        // 为修改之前，获取原来的周期
        if (plannerInspection.getId() != null) {
            oldInfo = dao.findModel(plannerInspection.getId());
        }



        Enterprise enterprise = SessionKeyUtils.getSessionEnterprise(request);
        SystemUser systemUser = SessionKeyUtils.getSessionUser(request);
        QueryParam queryParam=new QueryParam();
        queryParam.getSqlMap().put("orderName",plannerInspection.getName());
        queryParam.getSqlMap().put("enterprise",enterprise.getId()+"");
        List<PlannerInspection>plannerInspections=dao.findList(queryParam);
        if((CollectionUtils.isNotEmpty(plannerInspections)&& plannerInspection.getId()==null)||(plannerInspection.getId()!=null&&CollectionUtils.isNotEmpty(plannerInspections)&&plannerInspections.size()==1&&!plannerInspections.get(0).getId().equals(plannerInspection.getId()))){
            return ResultUtil.error("工单名称不能重复");
        }

        plannerInspection.setEnterprise(enterprise);
        plannerInspection.setCreateUser(systemUser);
        int flag = plannerInspection.getId() == null ? 0 : 1;//新增还是编辑
        //上传资料操作
        if ("1".equals(sImg1)) {
            //首先删除之前的关联资料文件
            plannerInspection.setResource(null);
            //如果有新资料文件 再存新资料文件
            String savePath1 = FileUtils.fileUpload(pic1, ConstantKeyFilePath.INSPECTION_SAFETY_PDF_DIR, ConstantKeyFilePath.INSPECTION_SAFETY_PDF_FIX, Configuration.getConfigurationByName("fileSaveRootPath"));
            if (StringUtils.isNotEmpty(savePath1)) {
                Resource resource = new Resource();
                String resourceName = pic1.getOriginalFilename();
                resource.setPath(savePath1);
                resource.setEnterprise(enterprise);
                resource.setResourceName(resourceName);
                resourceBiz.addOrUpdate(resource);
                resource.setResourceTypeEnum(ResourceTypeEnum.PDF);
                plannerInspection.setResource(resource);
            }
        } else {
            if(resourceId!=null && !"".equals(resourceId)) {
                Resource pInfo = resourceBiz.findModel(Long.valueOf(resourceId));
                plannerInspection.setResource(pInfo);
            }
        }
        plannerInspection.setStartTime(StringConverters.ToDateOnly(start));
        plannerInspection.setEndTime(StringConverters.ToDateOnly(end));
        if (CollectionUtils.isNotEmpty(selectCompleteAuditFlowIds)) {
            AuditFlow completeFlow = auditFlowBiz.findModel(StringConverters.ToLong(selectCompleteAuditFlowIds.get(0)));
            plannerInspection.setCompleteFlow(completeFlow.getFlow());
            plannerInspection.setAuditComplete(completeFlow);
        } else {
            //默认审批流
            if (auditFlowBiz.getDefaultFlow("complete", enterprise,3) != null) {
                plannerInspection.setAuditComplete(auditFlowBiz.getDefaultFlow("complete", enterprise,3));
                plannerInspection.setCompleteFlow(auditFlowBiz.getDefaultFlow("complete", enterprise,3).getFlow());
            }
        }
        if (CollectionUtils.isNotEmpty(selectDelayAuditFlowIds)) {
            AuditFlow delayFlow = auditFlowBiz.findModel(StringConverters.ToLong(selectDelayAuditFlowIds.get(0)));
            plannerInspection.setDelayFlow(delayFlow.getFlow());
            plannerInspection.setAuditDelay(delayFlow);
        } else {
            //默认审批流
            if (auditFlowBiz.getDefaultFlow("delay", enterprise,3) != null) {
                plannerInspection.setAuditDelay(auditFlowBiz.getDefaultFlow("delay", enterprise,3));
                plannerInspection.setDelayFlow(auditFlowBiz.getDefaultFlow("delay", enterprise,3).getFlow());
            }
        }
        if (CollectionUtils.isNotEmpty(selectCancelAuditFlowIds)) {
            AuditFlow cancelFlow = auditFlowBiz.findModel(StringConverters.ToLong(selectCancelAuditFlowIds.get(0)));
            plannerInspection.setAuditCancel(cancelFlow);
            plannerInspection.setCancelFlow(cancelFlow.getFlow());
        } else {
            //默认审批流
            if (auditFlowBiz.getDefaultFlow("cancel", enterprise,3) != null) {
                plannerInspection.setCancelFlow(auditFlowBiz.getDefaultFlow("cancel", enterprise,3).getFlow());
                plannerInspection.setAuditCancel(auditFlowBiz.getDefaultFlow("cancel", enterprise,3));
            }
        }
        if (CollectionUtils.isNotEmpty(selectOrganizationIds)) {
            plannerInspection.setOrganization(organizationBiz.findModel(StringConverters.ToLong(selectOrganizationIds.get(0))));
        }
        if (CollectionUtils.isNotEmpty(selectPeriodInstallIds)) {
            plannerInspection.setPeriodInstall(periodInstallBiz.findModel(StringConverters.ToLong(selectPeriodInstallIds.get(0))));
        }

        if (plannerInspection.getId() == null) {
            dao.add(plannerInspection);
        } else {
            dao.update(plannerInspection);
        }
        plannerInspection.setFacilityInspections(facilityInspectionBiz.findByIds(facilityMaintainIds, plannerInspection));
        //清空无效维保内容
        facilityInspectionBiz.deleteUselessData();
        //操作日志
        plannerInspectionLogBiz.savePlannerLog(plannerInspection, flag == 0 ? InsOrderOperationEnum.CREATE_PLANNER : InsOrderOperationEnum.EDIT, request);


        if (oldInfo != null) {
            // 修改操作
            if( plannerInspection.getId() != null && !oldInfo.getPeriodInstall().equals(plannerInspection.getPeriodInstall())) {
                // 如果是修改操作，且没有修改周期，不重新生成工单
                //TODO周期性计划生成事件列表保存到临时表中，方便调度生成工单
                try {
                    ThreadUtils.InsExecuteOrder(periodInstallBiz, plannerInspection);
                } catch (Exception e) {
                    logger.error("计划工单创建异常", e.getMessage(),e);
                }

            }
        } else  {
            // 新增操作
            //TODO周期性计划生成事件列表保存到临时表中，方便调度生成工单
            ThreadUtils.InsExecuteOrder(periodInstallBiz, plannerInspection);
        }



        return ResultUtil.success();
    }

    /**
     * 指派人员
     *
     * @param assignIds
     * @param plannerId
     * @return
     */
    public ResultDto assignUsers(String assignIds, String plannerId, HttpServletRequest request) {
        net.sf.json.JSONArray jsonArray = net.sf.json.JSONArray.fromObject(assignIds);
        PlannerInspection plannerInspection = dao.findModel(StringConverters.null2Long(plannerId));
        Set<SystemUser> systemUsers = plannerInspection.getAssignUsers();
        if (systemUsers == null) {
            systemUsers = new HashSet<>();
        }
        for (Object id : jsonArray) {
            SystemUser systemUser = systemUserBiz.findModel(StringConverters.null2Long(id));
            if (systemUser != null) {
                systemUsers.add(systemUser);
            }
        }
        plannerInspection.setAssign(Boolean.TRUE);
        plannerInspection.setInsOrderAssignTypeEnum(InsOrderAssignTypeEnum.USER);
        plannerInspection.setAssignUsers(systemUsers);
        dao.update(plannerInspection);
        //操作日志
        plannerInspectionLogBiz.savePlannerLog(plannerInspection, InsOrderOperationEnum.ASSIGN_USER, request);
        return ResultUtil.success();
    }

    /**
     * 指派岗位
     *
     * @param assignIds
     * @param plannerId
     * @return
     */
    public ResultDto assignPositions(String assignIds, String plannerId, HttpServletRequest request) {
        net.sf.json.JSONArray jsonArray = net.sf.json.JSONArray.fromObject(assignIds);
        PlannerInspection plannerInspection = dao.findModel(StringConverters.null2Long(plannerId));
        Set<Position> positions = plannerInspection.getAssignPositions();
        if (positions == null) {
            positions = new HashSet<>();
        }
        for (Object id : jsonArray) {
            Position position = positionBiz.findModel(StringConverters.null2Long(id));
            if (positions != null) {
                positions.add(position);
            }
        }
        plannerInspection.setAssign(Boolean.TRUE);
        plannerInspection.setInsOrderAssignTypeEnum(InsOrderAssignTypeEnum.POSITION);
        plannerInspection.setAssignPositions(positions);
        dao.update(plannerInspection);
        //操作日志
        plannerInspectionLogBiz.savePlannerLog(plannerInspection, InsOrderOperationEnum.ASSIGN_POSITION, request);
        return ResultUtil.success();
    }

    /**
     * 强制生成指定日实施单
     *
     * @param id
     * @param delay
     * @param delayDate
     * @return
     */
    public ResultDto saveAssignDate(String id, String delay, String delayDate, HttpServletRequest request) {
        PlannerInspection plannerInspection = dao.findModel(StringConverters.null2Long(id));
        if (StringConverters.null2Boolean(delay)) {
            plannerInspection.setDelay(StringConverters.null2Boolean(delay));
            plannerInspection.setDelayDate(StringConverters.ToDatePattern(delayDate, "yyyy-MM-dd HH:mm"));
            dao.update(plannerInspection);
            //TODO 周期性计划生成事件列表保存到临时表中，方便调度生成工单
            ThreadUtils.InsExecuteOrder(periodInstallBiz, plannerInspection);
            //操作日志
            plannerInspectionLogBiz.savePlannerLog(plannerInspection, InsOrderOperationEnum.ASSIGN_DATE, request);
        } else {
            //TODO 在此调用生成一次性工单的方法，开始时间，delayDate,结束时间，plannerInspection.getEndTime()+23:59:59
            inspectionOrderBiz.makeInspectionOrder(plannerInspection,StringConverters.formatDate(delayDate,"yyyy-MM-dd HH:mm"),DateTimeUtils.getEndOfDay1(plannerInspection.getEndTime()),0,null);
        }
        return ResultUtil.success();
    }


    /**
     * app接口保存周期计划
     * @param request
     * @return
     */
    @Transactional(readOnly = false)
    public ResultDto savePlanner(String name,String degree,String startTime,String endTime,String required,String remindTime,String periodId,
                                 String  assignUser,String assignPosition,String completeAuditId,String delayAuditId,String cancelAuditId,
                                 String inspectionData, HttpServletRequest request){
        Enterprise enterprise=SessionKeyUtils.getSessionEnterprise(request);
        SystemUser systemUser=SessionKeyUtils.getSessionUser(request);
        if(enterprise==null || systemUser==null){
            return ResultUtil.error("登陆过期，请重新登陆");
        }

        PlannerInspection plannerInspection=new PlannerInspection();
        plannerInspection.setEnterprise(enterprise);
        plannerInspection.setCreateUser(systemUser);
        plannerInspection.setSerial(StringConverters.getRandomString(10));
        plannerInspection.setName(name);
        plannerInspection.setDegree(degree);
        plannerInspection.setStartTime(StringConverters.formatDate(startTime,"yyyy-MM-dd"));
        plannerInspection.setEndTime(StringConverters.formatDate(endTime,"yyyy-MM-dd"));
        plannerInspection.setRequired(required);
        plannerInspection.setRemindTime(StringConverters.null2Int(remindTime));
        //所属周期
        PeriodInstall periodInstall=periodInstallBiz.findModel(StringConverters.null2Long(periodId));
        if(periodInstall==null){
            return ResultUtil.error("周期选择有误，请重新选择");
        }
        plannerInspection.setPeriodInstall(periodInstall);
        //指派数据
        JSONArray userArray=JSONArray.fromObject(assignUser);
        JSONArray positionArray=JSONArray.fromObject(assignPosition);
        if(userArray.size()!=0&& positionArray.size()!=0){
            return ResultUtil.error("指派只能选择一种类型");
        }else if(userArray.size()!=0){//指派人员
            plannerInspection.setInsOrderAssignTypeEnum(InsOrderAssignTypeEnum.USER);
            Set<SystemUser>systemUserSet=new HashSet<>();
            userArray.forEach(x->{
                systemUserSet.add(systemUserBiz.findModel(StringConverters.null2Long(x)));
            });
            plannerInspection.setAssign(true);
            plannerInspection.setAssignUsers(systemUserSet);
        }else if(positionArray.size()!=0){//指派岗位
            plannerInspection.setInsOrderAssignTypeEnum(InsOrderAssignTypeEnum.POSITION);
            Set<Position>positionHashSet=new HashSet<>();
            positionArray.forEach(x->{
                positionHashSet.add(positionBiz.findModel(StringConverters.null2Long(x)));
            });
            plannerInspection.setAssignPositions(positionHashSet);
            plannerInspection.setAssign(true);
        }
        AuditFlow completeFlow=auditFlowBiz.findModel(StringConverters.null2Long(completeAuditId));//完成审批流
        if(completeFlow==null){
            completeFlow=auditFlowBiz.getDefaultFlow("complete",enterprise,3);
        }
        plannerInspection.setCompleteFlow(completeFlow!=null?completeFlow.getFlow():"");
        plannerInspection.setAuditComplete(completeFlow);

        AuditFlow delayFlow=auditFlowBiz.findModel(StringConverters.null2Long(delayAuditId));//延期审批流
        if(delayFlow==null){
            delayFlow=auditFlowBiz.getDefaultFlow("delay",enterprise,3);
        }
        plannerInspection.setDelayFlow(delayFlow!=null?delayFlow.getFlow():"");
        plannerInspection.setAuditDelay(delayFlow);

        AuditFlow cancelFlow=auditFlowBiz.findModel(StringConverters.null2Long(cancelAuditId));//取消审批流
        if(cancelFlow==null){
            cancelFlow=auditFlowBiz.getDefaultFlow("cancel",enterprise,3);
        }
        plannerInspection.setCancelFlow(cancelFlow!=null?cancelFlow.getFlow():"");
        plannerInspection.setAuditCancel(cancelFlow);
        dao.add(plannerInspection);
        //设备工艺数据
        JSONArray inspectionArray=JSONArray.fromObject(inspectionData);
        if(inspectionArray.size()==0){
            return ResultUtil.success("请添加设备");
        }
        Set<FacilityInspection>facilityInspectionSet=new HashSet<>();
        inspectionArray.forEach(x->{
            String inspectionId=JSONObject.fromObject(x).getString("inspectionId");
            String facilityId=JSONObject.fromObject(x).getString("facilityId");
            FacilityInspection facilityInspection= facilityInspectionBiz.saveFacilityInspection(plannerInspection.getId()+"",facilityId,inspectionId, enterprise);
//            if(facilityMaintain==null){
//                return ResultUtil.error("添加的设备或工作要求有误");
//            }
            facilityInspectionSet.add(facilityInspection);
            plannerInspection.setFacilityInspections(facilityInspectionSet);
            dao.update(plannerInspection);
        });
        plannerInspectionLogBiz.savePlannerLog(plannerInspection,  InsOrderOperationEnum.CREATE_PLANNER, request);//log日志
        //TODO 周期性计划生成事件列表保存到临时表中，方便调度生成工单
        ThreadUtils.InsExecuteOrder(periodInstallBiz, plannerInspection);
        return ResultUtil.success();
    }

    //导出年度计划的设备基础数据
    public  List<Map<String, Object>> getYearPlan(String organizationId, String enterpriseId) {
        List<Map<String, Object>> mapList = new ArrayList<>();
        QueryParam queryParam=new QueryParam();
        queryParam.getSqlMap().put("enterpriseId",enterpriseId);
        queryParam.getSqlMap().put("organizationId",organizationId);

        List<Facility>facilityList=facilityBiz.findList(queryParam);
        facilityList.forEach(facility ->{
            Map<String, Object> testMap = new HashMap<>();
            testMap.put("code",facility.getCode());
            testMap.put("name",facility.getName());
            testMap.put("type",facility.getType()!=null?facility.getType():"");
            testMap.put("facilityId",facility.getId());
            mapList.add(testMap);
        } );
        return mapList;
    }
}
